package cn.relx.user.service.impl;

import cn.relx.basic.config.BussinessException;
import cn.relx.basic.constant.BaseConstans;
import cn.relx.basic.util.EmailUtil;
import cn.relx.basic.util.MD5Utils;
import cn.relx.basic.util.StrUtils;
import cn.relx.basic.vo.RegisterVo;
import cn.relx.user.domain.Logininfo;
import cn.relx.user.domain.User;
import cn.relx.user.mapper.LogininfoMapper;
import cn.relx.user.mapper.UserMapper;
import cn.relx.user.service.IUserService;
import cn.relx.basic.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author relx
 * @since 2022-10-19
 */
@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional
    public void phoneCodeRegister(RegisterVo registerVo) {
        //参数为空校验
        //两次密码是否一致
        if (!registerVo.getPassword().equals(registerVo.getConfirmPassword())){
            throw new BussinessException("两次密码不一致，请重新输入!");
        }
        //注册手机号码与获取验证码手机号码是否一致
        //拼接手机验证码的redisKey
        String smsCodeKey = BaseConstans.VerifyCodeConstant.BUSINESS_REGISTER_PREFIX + registerVo.getPhone();
        //根据redisKey获取值，如果获取不到说明此手机号错误或者已过期
        Object smsCodeValueTmp = redisTemplate.opsForValue().get(smsCodeKey);
        if(smsCodeValueTmp == null){
            throw new BussinessException("验证码已过期，请重新输入!");
        }
        //判断短信验证码是否一致
        //获取redis中的短信验证码
        String[] split = smsCodeValueTmp.toString().split(":");
        String smsCode = split[0];
        //判断验证码是否存在，如果不存在说明已过期
        if(!smsCode.equalsIgnoreCase(registerVo.getSmsCodeValue())){
            throw new BussinessException("验证码错误，请重新输入！");
        }
        //将registerVo数据拷贝到user对象
        User user = registerVoUser(registerVo);
        //将registerVo数据拷贝到logininfo
        Logininfo logininfo = userLogininfo(user);
        logininfo.setType(1);
        //保存logininfo数据，需要设置反悔自增长Id，因为需要设置user的外键
        logininfoMapper.add(logininfo);
        //保存user用户数据
        user.setLogininfoId(logininfo.getId());
        user.setState(0);
        userMapper.add(user);
    }

    @Override
    @Transactional
    public void emailCodeRegister(RegisterVo registerVo) {
        User user = userMapper.findByEmail(registerVo.getEmail());
        if(StringUtils.isBlank(registerVo.getEmail())){
            throw new BussinessException("邮箱不能为空，请重新输入！");
        }
        if(user != null){
            throw new BussinessException("邮箱已注册，请直接登录！");
        }
        //两次密码是否一致
        if (!registerVo.getPassword().equals(registerVo.getConfirmPassword())){
            throw new BussinessException("两次密码不一致，请重新输入!");
        }
        //将registerVo数据拷贝到user对象
        User user1 = registerVoUser(registerVo);
        //将registerVo数据拷贝到logininfo
        Logininfo logininfo = userLogininfo(user1);
        logininfo.setType(1);
        //保存logininfo数据，需要设置反悔自增长Id，因为需要设置user的外键
        logininfoMapper.add(logininfo);
        //保存user用户数据
        user1.setLogininfoId(logininfo.getId());
        user1.setState(0);
        userMapper.add(user1);
        EmailUtil.Email(registerVo.getEmail(),
                "激活后注册成功!"
                + "激活链接:http://localhost:80/user/audit/"+user1.getId(),"注册请手动激活!");
    }

    @Override
    @Transactional
    public void emailAuditRegister(Long id) {
        userMapper.updateByState(id);
    }

    /**
     * 将register封装到user中
     * @param registerVo
     * @return
     */
    public User registerVoUser(RegisterVo registerVo){
        User user = new User();
        user.setPhone(registerVo.getPhone());
        user.setUsername(registerVo.getPhone());
        user.setEmail(registerVo.getEmail());
        //将铭文密码使用MD5进行盐值加密
        String salt = StrUtils.getComplexRandomString(32);
        String md5 = MD5Utils.encrypByMd5(registerVo.getPassword() + salt);
        user.setPassword(md5);
        user.setSalt(salt);
        return user;
    }

    public Logininfo userLogininfo(User user){
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(1);
        return logininfo;
    }
}
